package com.fingard.dsp.bank.directbank.ccb12;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.helpers.YBTHelper;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 建行银保通批量代收付
 * 
 * @author Cruise
 * @date 2019/4/3
 */
public class CCB12BatPayRec extends CCB12Base implements IBatPayRec {
	@Override
	public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
		return d_BatPayRec(p_req1988);
	}

	@Override
	public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
		return d_QryBatPayRec(p_req1998);
	}

	@Override
	public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
		return d_BatPayRec(p_req9188);
	}

	@Override
	public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
		return d_QryBatPayRec(p_req9198);
	}
	
	/**
	 * 批量代收付提交
	 * 批量送盘	P53818105
	 * @param p_reqBat
	 * @return
	 * @throws Exception
	 */
	public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
		RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
		retAts.reqSeqID = p_reqBat.reqBatchNO;
		
		try {
			// 生成批量代收付提交文件名,命名规则:触发方式+系统+类型+建行一级分行编号+保险公司号+日期+批量包序号
			Date tmpPaySendDate = YBTHelper.getDateCutTime(p_reqBat.getPayDateTime(), getBankConfig().getValueAsString("dayCutTime"));
			
			// 批量代收付提交文件名命名规则:
//			1、触发批量交易方式：A- 自动触发	H-手工触发（暂时未用到）
//			2、系统定义：	A-不分系统 L-寿险	P-产险	G-团险 其中A,G暂时未用到
//			3、类型定义：	0-批扣 		1-批付；
			String payType = "";
			if (p_reqBat.reqHeader.isBatRec) {
				payType = "0";
			} else {
				payType = "1";
			}
//			4、分行编号：	3位银行代码，见建行方一级分行代码，取前三位；
			String branchCode = p_reqBat.ownArea;
			if (branchCode.length() != 3) {
				retAts.respCode = "0";
				retAts.respInfo = "建行方一级分行代码必须为3位，实际分行代码为:[" + branchCode + "].";
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
//			5、保险公司号：3位保险公司号，见保险公司号，取后三位；
			String corpNo = "";
			String useBranchCorpNo = getBankConfig().getValueAsString("useBranchCorpNo");
			if (StringHelper.hasAnyChar(useBranchCorpNo)) {
				corpNo = getBankConfig().getMapValueByKey("corpNoMapping", p_reqBat.ownAct);
			} else {
				corpNo = bankFront.corpNo;
			}
			if (StringHelper.isNullOrEmpty(corpNo)) {
				retAts.respCode = "0";
				retAts.respInfo = "'保险公司号'为空,请检查BankFront.xml相关配置信息!";
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = FailCode.E9981;
				retAts.writeRetToATS();
				return retAts;
			}
//			6、日期：年+月+日(YYYYMMDD)；20080623， 月、日不足两位，补零；
			String transDate = Format.Date8Format.format(tmpPaySendDate);
//			7、批量包序号：01：表示第一个批量包，02：表示第二个批量包，以此类推；
			String tmpBatSeqNo = "";
			if (p_reqBat.reqHeader.isBatRec) {
				tmpBatSeqNo = YBTHelper.getBatSeqNo(getTempFileDirectory() + File.separator + "BatRec", 2);
			} else {
				tmpBatSeqNo = YBTHelper.getBatSeqNo(getTempFileDirectory() + File.separator + "BatPay", 2);
			}
			String tmpBatPackageName = "AL" + payType + branchCode + corpNo + transDate + tmpBatSeqNo;
			
			XmlTextWriter xmlWriter = new XmlTextWriter();
			xmlWriter.autoFormat = false;
			xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\"?>");
			xmlWriter.writeStartElement("Root");
			
			// 报文头部  /Root/Head
			xmlWriter.writeStartElement("Head");
			/** 代理保险批量包名称 */
			xmlWriter.writeElementString("AgIns_BtchBag_Nm", tmpBatPackageName);
            /** 代理保险批量包处理状态代码 */
             xmlWriter.writeElementString("AgInsBtchBagPcsg_StCd", "00");
			/** 当前批明细总笔数 */
			xmlWriter.writeElementString("Cur_Btch_Dtl_TDnum", p_reqBat.totalNum);
			/** 当前批明细总金额 */
			xmlWriter.writeElementString("Cur_Btch_Dtl_TAmt", p_reqBat.totalAmt);
			/** 代理保险批量包类型代码 */
			xmlWriter.writeElementString("AgIns_BtchBag_TpCd", "");
			xmlWriter.writeEndElement();
			
			StringBuilder tmpSeqNoContent = new StringBuilder();
			
			// 报文体 /Root/Detail_List/Detail
			xmlWriter.writeStartElement("Detail_List");
			while(p_reqBat.readRecord()) {
				if (tmpSeqNoContent.length() > 0) {
					tmpSeqNoContent.append("\r\n");
				}
				tmpSeqNoContent.append(p_reqBat.readedDetail.askNumber);
				
				String oppAct = "";
				String oppName = "";
				if (p_reqBat.reqHeader.isBatRec) {
					oppAct = p_reqBat.readedDetail.payAct;
					oppName = p_reqBat.readedDetail.payName;
				} else {
					oppAct = p_reqBat.readedDetail.recAct;
					oppName = p_reqBat.readedDetail.recName;
				}
				
				String batBusiType = "";
				if (p_reqBat.reqHeader.isBatRec) {
					batBusiType = getBankConfig().getSetValue("businessType", "Memo", "9188");
					if (StringHelper.hasAnyChar(batBusiType)) {
						batBusiType = getBankConfig().getMapValueByKey("batRecBusiCode", batBusiType);
					} else {
						batBusiType = "02";// 默认值:续期缴费
					}
				} else {
					batBusiType = getBankConfig().getSetValue("businessType", "Usage", "1988");
					if (StringHelper.hasAnyChar(batBusiType)) {
						batBusiType = getBankConfig().getMapValueByKey("batPayBusiCode", batBusiType);
					} else {
						batBusiType = "12";// 默认值:保险理赔
					}
				}
				
				XElement tmpXElement = new XElement("Detail", "");
				/** 客户名称 */
		        tmpXElement.addChild(new XElement("Cst_Nm", oppName));
		        /** 客户账号 */
		        tmpXElement.addChild(new XElement("Cst_AccNo", oppAct));
				/** 币种代码 */
		        tmpXElement.addChild(new XElement("CcyCd", "156"));
				/** 钞汇代码(1-钞、2-汇) */
		        tmpXElement.addChild(new XElement("CshEx_Cd", "1"));
				/** 批量明细序号 */
		        tmpXElement.addChild(new XElement("Btch_Dtl_SN", p_reqBat.readedDetail.askNumber));
				/** 保险公司代收付业务种类代码 */
		        tmpXElement.addChild(new XElement("Ins_Co_SRP_Bsn_CtCd", batBusiType));
				/** 保单号码 */
		        tmpXElement.addChild(new XElement("InsPolcy_No", p_reqBat.readedDetail.sourceNoteCode));
				/** 金额 */
		        tmpXElement.addChild(new XElement("Amt", p_reqBat.readedDetail.payAmount));
				/** 续期应缴期数 */
		        tmpXElement.addChild(new XElement("Rnew_Pbl_Prd_Num", ""));
				/** 备用字段1信息 */
		        tmpXElement.addChild(new XElement("Rsrv_Fld1_Inf", ""));
				/** 备用字段2信息 */
		        tmpXElement.addChild(new XElement("Rsrv_Fld2_Inf", ""));
				/** 备用字段3信息 */
		        tmpXElement.addChild(new XElement("Rsrv_Fld3_Inf", ""));
		        
		        nodeAnalysis(p_reqBat.readedDetail.srcXElement, tmpXElement, getCharset());
		        xmlWriter.writeXElement(tmpXElement);
			}
			xmlWriter.writeEndDocument();
			WriteBankLogStep2(xmlWriter.toXmlString());

			// 批次请求文件写入本地
			String tmpLocalMarkPath = "";
			if (p_reqBat.reqHeader.isBatRec) {
				tmpLocalMarkPath = getTempFileDirectory() + File.separator + "BatRec" + File.separator + tmpBatPackageName + "_SOURCE.xml";
			} else {
				tmpLocalMarkPath = getTempFileDirectory() + File.separator + "BatPay" + File.separator + tmpBatPackageName + "_SOURCE.xml";
			}
			WriteBankLogLn2("批次交易文件本地保存路径:\r\n" + tmpLocalMarkPath);
			FileHelper.writeFile(tmpLocalMarkPath, xmlWriter.toXmlString(), getCharset());
			
			// 批次映射文件写入本地
			WriteBankLogLn2("批次映射文件内容:\r\n" + tmpSeqNoContent.toString());
			String tmpLocalMappingFile = getDataFileDirectory(tmpPaySendDate) + File.separator + p_reqBat.reqBatchNO + "_" + tmpBatPackageName + ".txt";
			WriteBankLogLn2("批次映射文件本地保存路径:\r\n" + tmpLocalMappingFile);
			FileHelper.writeFile(tmpLocalMappingFile, tmpSeqNoContent.toString(), getCharset());
			
			// 上送银保通服务器
			FtpSet ftpSet = bankFront.getFtpSet("bat");
			
			FtpReceiver ftpReceiver = null;
			String requestType = getBankConfig().getValueAsString("requestType");
			if (requestType != null && "SFTP".equalsIgnoreCase(requestType)) {
				SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
				String sftpFilePath = StringHelper.trimEnd(ftpSet.upDir, "/") + "/" + tmpBatPackageName + "_SOURCE.xml";
				ftpReceiver = sftpPortClient.uploadFile("", tmpLocalMarkPath, sftpFilePath);
				sftpPortClient.disconnect();
			} else {
				FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
	            ftpReceiver = ftpPortClient.uploadFile(tmpLocalMarkPath, tmpBatPackageName + "_SOURCE.xml");
	            ftpPortClient.disconnect();
			}
			
			retAts.respCode = "0";
            if (!ftpReceiver.isCompleted) {
                retAts.respCode = "-1";
                retAts.respInfo = ftpReceiver.connMsg;
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
            	retAts.respInfo = "上传失败";
            	retAts.transState = "BatchFailed";
            	retAts.payInfoCode = "E9999";
            } else {
            	retAts.respInfo = "上传成功";
            	retAts.transState = "Uploaded";
            	retAts.payInfoCode = "I4001";
            }
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.respCode = "-1";
			retAts.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		} 
		
		retAts.writeRetToATS();
		return retAts;
	}
	
	/**
	 * 批量代收付查询
	 * 
	 * @param p_reqQryBat
	 * @return
	 * @throws Exception
	 */
	public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
		RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
		retAts.reqSeqID = p_reqQryBat.reqBatchNO;
		
		try {
			Date tmpPaySendDate = getDayCutTime(p_reqQryBat.getBgnDateTime());
			
			// 获取批量代收付下载结果文件名,命名规则:触发方式+系统+类型+建行一级分行编号+保险公司号+日期+批量包序号
			String tmpBatPackageName = "";
			
			// 本地批次映射文件读取
			File localMappingDir = new File(getDataFileDirectory(tmpPaySendDate));
			if (localMappingDir.exists()) {
				File[] localMappingFileList = localMappingDir.listFiles();
				for (File tmpLocalMappingFile : localMappingFileList) {
					WriteBankLogLn("当前批次映射文件路径:" + tmpLocalMappingFile.getAbsolutePath());
					String tmpLocalMappingBatSeqNo = tmpLocalMappingFile.getName().replace(".txt", "");
					if (p_reqQryBat.reqBatchNO.equals(tmpLocalMappingBatSeqNo.split("_")[0])) {
						tmpBatPackageName = tmpLocalMappingBatSeqNo.split("_")[1];
						WriteBankLogLn("当前批次待下载文件批量包名称:" + tmpBatPackageName);
					}
				}
				if (StringHelper.isNullOrEmpty(tmpBatPackageName)) {
					retAts.respCode = "-1";
	        		retAts.respInfo = "本地批次待下载文件批量包名称为空,未找到关联映射文件!";
	        		retAts.writeAfterDetail();
	        		return retAts;
				}
			} else {
				retAts.respCode = "-1";
        		retAts.respInfo = "本地批次映射文件路径:[" + localMappingDir.getAbsolutePath() + "]目录不存在,未发生交易!";
        		retAts.writeAfterDetail();
        		return retAts;
			}

            String suffix = getBankConfig().getValueAsString("suffix");
            if (StringHelper.isNullOrEmpty(suffix)) {
                suffix = "xml";
            }
            String tmpLocalMarkPath = createTempFileDirectory() + File.separator + tmpBatPackageName + "_RESULT." + suffix;
			WriteBankLogLn2("批次结果文件保存本地路径: " + tmpLocalMarkPath);
			
			FtpSet ftpSet = bankFront.getFtpSet("bat");
            String sftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + tmpBatPackageName + "_RESULT." + suffix;
			WriteBankLogLn2("待下载FTP/SFTP服务器文件路径:" + sftpFilePath);
			FtpReceiver ftpReceiver = null;
			String requestType = getBankConfig().getValueAsString("requestType");
			if (requestType != null && "SFTP".equalsIgnoreCase(requestType)) {
				SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
	            ftpReceiver = sftpPortClient.downloadFile("", tmpBatPackageName + "_RESULT." + suffix, tmpLocalMarkPath);
	            sftpPortClient.disconnect();
			} else {
				FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
				WriteBankLogLn("开始遍历ftp目录:" + ftpSet.downDir);
				List<String> list = ftpPortClient.listNames(ftpSet.downDir);
				Iterator<String> iterator = list.iterator();
				while (iterator.hasNext()) {
					WriteBankLogLn("当前文件名:" + iterator.next());
				}
				ftpReceiver = ftpPortClient.downloadFile(tmpBatPackageName + "_RESULT." + suffix, tmpLocalMarkPath);
				ftpPortClient.disconnect();
			}
			
			if (ftpReceiver.isCompleted) {
            	String tmpStrRet = FileHelper.readFileText(tmpLocalMarkPath, getCharset());
            	WriteBankLogLn2("本地批次结果文件内容:\r\n" + tmpStrRet);
            	
            	if (StringHelper.hasAnyChar(tmpStrRet)) {
            		retAts.respCode = "0";
					
            		StringBuilder tmpSbMsg = new StringBuilder();
					XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet, tmpSbMsg);
					
					String tmpHeadRetCode = tmpBkReader.getFirstText("/Root/Head/AgInsBtchBagPcsg_StCd");
					if ("00".equals(tmpHeadRetCode)) {
						String tmpResultPackageFile = tmpBkReader.getFirstText("/Root/Head/AgIns_BtchBag_Nm");
						if (tmpBatPackageName.equals(tmpResultPackageFile)) {
							while(tmpBkReader.read("/Root/Detail_List/Detail")) {
								RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
								if ("9198".equals(p_reqQryBat.reqHeader.transType)) {
									tmpRetDetail.recAct = p_reqQryBat.ownAct;
									tmpRetDetail.payAct = tmpBkReader.readedXElement.getSingleText("Cst_AccNo");
									tmpRetDetail.payName = tmpBkReader.readedXElement.getSingleText("Cst_Nm");
								} else {
									tmpRetDetail.payAct = p_reqQryBat.ownAct;
									tmpRetDetail.recAct = tmpBkReader.readedXElement.getSingleText("Cst_AccNo");
									tmpRetDetail.recName = tmpBkReader.readedXElement.getSingleText("Cst_Nm");
								}
								tmpRetDetail.payAmount = Format.DecimalAmtFormat.format(Double.parseDouble(tmpBkReader.readedXElement.getSingleText("Amt")));
								
								String detailMemo = tmpBkReader.readedXElement.getSingleText("Rsrv_Fld1_Inf");
								if (StringHelper.hasAnyChar(detailMemo)) {
									tmpRetDetail.postScript = detailMemo;
								} else {
									tmpRetDetail.postScript = tmpBkReader.readedXElement.getSingleText("Btch_Dtl_SN");
									if(tmpRetDetail.postScript.length()<6){
										int asknum = Integer.parseInt(tmpRetDetail.postScript);
										tmpRetDetail.postScript = String.format("%06d",asknum);
									}
								}
								
								tmpRetDetail.result = tmpHeadRetCode + "+" + tmpBkReader.readedXElement.getSingleText("Hst_Rsp_Cd");
								tmpRetDetail.payInfoCode = tmpBkReader.readedXElement.getSingleText("Hst_Rsp_Cd");
								String memo = tmpBkReader.readedXElement.getSingleText("Hst_Rsp_Inf");
								tmpRetDetail.memo = memo;
								if ("EMFBA".equals(tmpRetDetail.payInfoCode)) {
									int index = memo.indexOf("@@,@@");
									if (index > 0) {
										memo = memo.substring(index+5);
										int tmpIndex = memo.indexOf("@@");
										if (tmpIndex > 0) {
											memo = memo.substring(0, tmpIndex);
										}
									} else {
										index = memo.indexOf(":")+1;
										int tmpIndex = memo.indexOf("#");
										if (tmpIndex > index && index > 1) {
											memo = memo.substring(index, tmpIndex);
										}
									}
									tmpRetDetail.payInfoCode = memo;
								} 
								
								retAts.writeRetDetail(tmpRetDetail);
							}
						} else {
							retAts.respCode = "-1";
		            		retAts.respInfo = "返回批量包名[" + tmpResultPackageFile + "]与预期批量包名[" + tmpBatPackageName + "]不一致.";
						}
					} else {
						retAts.respInfo = tmpBkReader.getFirstText("/Root/Head/Rsp_Inf");
						retAts.transState = tmpHeadRetCode;
						retAts.payInfoCode = tmpHeadRetCode;
					}
            	} else {
            		retAts.respCode = "-1";
            		retAts.respInfo = "本地批次结果文件内容为空!";
            	}
            } else {
            	retAts.respCode = "-1";
    			retAts.respInfo = "批次结果文件下载失败:" + ftpReceiver.connMsg;
            }
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.respCode = "-1";
			retAts.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}
		
		retAts.writeAfterDetail();
		return retAts;
	}
}
